#include "TCTP.h"


void Add_CRC(unsigned char *puchMsg , unsigned char usDataLen)
{
    unsigned char crc = 0x00 ; 

    crc = PACKET_HEAD + PACKET_DATA + puchMsg[2] + puchMsg[3] + puchMsg[4];
    puchMsg[usDataLen] = crc; 
}
unsigned char Calc_CRC(unsigned char *puchMsg , unsigned char usDataLen)
{
    unsigned char CRC = 0x00;

    CRC = PACKET_HEAD + PACKET_DATA + puchMsg[usDataLen - 3] + puchMsg[usDataLen - 2] + puchMsg[usDataLen - 1];
    
    return CRC;
}

/*******************************************
函数名称：  TCTP_PackWithOutPacketVerify
功    能：  封装TCTP数据包（不带校验）
参    数：  TargetAddress   目标地址
            LocalAddress    本机地址
            Function        功能码
            Status          状态码
            *TctpBroker     数据包传送代理
返回值  ：  0 成功 
********************************************/
unsigned char TCTP_PackWithOutPacketVerify(unsigned char CMD,TCTP_Broker_T *TctpBroker)
{
    unsigned char i = 0;	

    //封装报文起始
    TctpBroker->Buffer[i++] = (unsigned char)(PACKET_HEAD);  
    
    //封装数据长度
    TctpBroker->Buffer[i++] = PACKET_DATA;     
    
      //封装命令
    TctpBroker->Buffer[i++] = CMD;     
    
    return 0;    
}

/*******************************************
函数名称：  TCTP_Pack
功    能：  封装TCTP数据包（带校验）
参    数：  TargetAddress   目标地址
            LocalAddress    本机地址
            Function        功能码
            Status          状态码
            *TctpBroker     数据包传送代理
返回值  ：  0 成功 
********************************************/
unsigned char TCTP_Pack(unsigned char CMD,TCTP_Broker_T *TctpBroker)
{
    TCTP_PackWithOutPacketVerify(CMD,TctpBroker);
    //初始化校验缓存	
		memset(TctpBroker->Buffer+5, 0, CRC_LEN);    
    Add_CRC(TctpBroker->Buffer,5);

    return 0;
}


/*******************************************
函数名称：  DDTP_PacketVerify
功    能：  校验DDTP数据包
参    数：  *DdtpPacket     目标数据包
            DdtpPacketSize  数据包大小
返回值  ：  0 校验成功 
            1 校验失败
            2 长度错误
            3 内存申请失败
********************************************/
unsigned char TCTP_PacketVerify(unsigned char *DdtpPacket,unsigned char DdtpPacketSize)
{
    /****************************方法1********************************/
    unsigned short CRC = 0;
    
    if(DdtpPacketSize > CRC_LEN)
    {
        CRC |= DdtpPacket[DdtpPacketSize];//提取接收到的CRC校验码低字节
        if(Calc_CRC(DdtpPacket,DdtpPacketSize-CRC_LEN) == CRC)//如果计算得到的校验码与接收到的校验码相同
        {
            return 0;//校验成功
        }
        else
        {
            return 1;//校验失败
        }
    }
    else
    {
        return 2;//长度错误
    }    
}

/*******************************************
函数名称：  DDTP_UnPackWithOutPacketVerify
功    能：  解析DDTP数据包（不带校验）
参    数：  *TargetAddress  目标地址
            *LocalAddress   本机地址
            *Function       功能码
            *Status         状态码
            *TctpBroker     数据包传送代理
返回值  ：  0 解析成功
********************************************/
unsigned char TCTP_UnPackWithOutPacketVerify(unsigned char *CMD,TCTP_Broker_T *TctpBroker)
{
    unsigned short i = 0;
    
    //跳过报文起始
    i++;
    i++;
    
    //跳过数据长度
    i++;
    i++;
    
    //解析状态码
    *CMD = 0;
    *CMD = TctpBroker->Buffer[i++];            

    return 0;//解析成功
}

/*******************************************
函数名称：  DDTP_UnPack
功    能：  解析DDTP数据包（带校验）
参    数：  *TargetAddress  目标地址
            *LocalAddress   本机地址
            *Function       功能码
            *Status         状态码
            *TctpBroker     数据包传送代理
返回值  ：  0 解析成功
            1 解析失败
            2 校验错误
********************************************/
unsigned char TCTP_UnPack(unsigned char *CMD,TCTP_Broker_T *TctpBroker)
{
    if(TCTP_PacketVerify(TctpBroker->Buffer,TctpBroker->BufferSize) == 0)//如果校验通过
    { 
        if(TCTP_UnPackWithOutPacketVerify(CMD,TctpBroker) == 0)
        {
            return 0;//解析成功
        }
        else
        {
            return 1;//解析失败
        }
    }
    else
    {
        return 2;//校验错误
    }
}

/*******************************************
函数名称：  DDTP_Load_Data
功    能：  装载数据
参    数：  *Data           待装载数据地址
            DataSize        待装载数据大小
            *DataBroker     装载数据代理
            Endian          装载字节次序
                            HOST_ENDIAN：按主机序（低字节在前）装载
                            NET_ENDIAN：按网络序（高字节在前）装载
返回值  ：  0 成功 
********************************************/
unsigned char TCTP_Load_Data(unsigned char *Data,unsigned char DataSize,TCTP_Broker_T *DataBroker,unsigned char Endian)
{
    unsigned char i;
    
    if(Endian == HOST_ENDIAN)
    {
        //按主机序（低字节在前）装载数据
        memcpy(DataBroker->Buffer+3,Data,DataSize); 
    }
    else
    {
        //按网络序（高字节在前）装载数据
        for(i=0;i<DataSize;i++)
        {
            DataBroker->Buffer[DataBroker->BufferOffset+i+HEAD_LEN] = *(Data+(DataSize-1-i));
        }
        DataBroker->BufferOffset += DataSize; 
    }

    return 0;
}

/*******************************************
函数名称：  DDTP_UnLoad_Data
功    能：  卸载数据
参    数：  *Data           卸载数据地址
            DataSize        卸载数据大小
            *DataBroker     待卸载数据代理
            Endian          卸载字节次序
                            HOST_ENDIAN：按主机序（低字节在前）卸载
                            NET_ENDIAN：按网络序（高字节在前）卸载
返回值  ：  0 成功 
********************************************/
unsigned char TCTP_UnLoad_Data(unsigned char *Data,unsigned char DataSize,TCTP_Broker_T *DataBroker,unsigned char Endian)
{
    unsigned short i;

    if(Endian == HOST_ENDIAN)
    {
        //按主机序（低字节在前）卸载数据
        memcpy(Data,DataBroker->Buffer+DataBroker->BufferOffset+HEAD_LEN,DataSize);
        DataBroker->BufferOffset += DataSize;
    }
    else
    {
        //按网络序（高字节在前）卸载数据
        for(i=0;i<DataSize;i++)
        {
            *(Data+(DataSize-1-i)) = DataBroker->Buffer[i+DataBroker->BufferOffset+HEAD_LEN];
        }
        DataBroker->BufferOffset += DataSize; 
    }

    return 0;
}

/*******************************************
函数名称：  DDTP_PacketFind
功    能：  查找DDTP数据包
参    数：  *Data           查找数据地址
            DataSize        查找数据大小
            *DataBroker     待处理数据代理
返回值  ：  0 成功 
            1 失败
********************************************/
unsigned char TCTP_PacketFind(unsigned char *Data,unsigned char DataSize,TCTP_Broker_T *DataBroker)
{
    unsigned char *addr = NULL;
    unsigned short Size = 0;
    unsigned short i = 0;
    unsigned short HEAD = PACKET_HEAD;

    addr = Data;//记录缓存起始地址
    if(addr != NULL)
    {
        for(i=0;i<DataSize;i++)//查找“0xFFFF”头
        {
            if(memcmp(addr,&HEAD,sizeof(HEAD)) == 0)//如果找到“0xA5”头
            {
                if((addr+3) < (Data+DataSize))//如果不会访问越界
                {
                    Size = 0;
                    Size |= ((addr[0])&0xFF); 
                    
                    if((addr+Size) < (Data+DataSize))//如果不会访问越界
                    {
                        if(Size >= sizeof(CRC_LEN))
                        {
                            if(TCTP_PacketVerify(addr,(Size+DATASIZE_LEN)) == 0)//如果校验通过
                            { 
                                DataBroker->Buffer = addr;//得到数据包地址
                                DataBroker->BufferSize = (Size+HEAD_LEN+DATASIZE_LEN);//得到数据包大小
                                
                                return 0;//校验通过
                            }
                        }
                    }
                }
            }
            
            addr++;
        }
    }
        
    return 1;//没有找到有效数据包

}

/*******************************************
函数名称：  DDTP_PacketDelete
功    能：  删除DDTP数据包
参    数：  *DataBroker     数据代理
返回值  ：  0 成功 
            1 失败
********************************************/
unsigned char TCTP_PacketDelete(TCTP_Broker_T *DataBroker)
{
    if(DataBroker->Buffer != NULL)
    {
        memset(DataBroker->Buffer,0,DataBroker->BufferSize);//删除数据包内容
        
        //DataBroker->Buffer = NULL;      //复位数据包地址
        DataBroker->BufferSize = 0;     //复位数据包大小
        DataBroker->BufferOffset = 0;   //复位数据包偏移
        
        return 0;//成功
    }
    else
    {
        return 1;//失败
    }

}


/* [] END OF FILE */
